﻿using System;
using System.Collections.Generic;
using System.Text;
using GeometryCSharp;
using AGHFiraPlayer.Strategies;

namespace AGHFiraPlayer.Strategies.StrategiesImpl
{
    class SimplePassStrategy : AbstractStrategy
    {
        //to powoduje problemy 
        private int CALCULATE_STEPS = 10;

        private double TOO_LONG = SimpleFunctions.TOO_LONG;
        private Point2D passPoint;
        private Point2D shotSpot = null;
        private static Point2D staticPoint = null;
        private Vector2D toGoal;
        private bool finished = false;
        private double eta;

        private const double CLEAR_WAY_FACTOR = 50;
        private const double TIME_FACTOR = 50;
        
        override public int applicabilityLevel(ref List<IStrategy> choosenStrategies) {

            Point2D tmpShotSpot;
            double maxScore = -1;
            foreach (RobotController robot in driver.Robots)
            {
                if (!robot.isUsedInStrategy)
                {
                    if (involvedRobots.Count == 0)
                    {
                        involvedRobots.Add(robot);
                    }
                    foreach (AbstractStrategy strategy in choosenStrategies)
                    {
                        if (strategy.getStrategyType() == StrategyType.Offensive || strategy.getStrategyType() == StrategyType.Passing)
                        {
                            return -1;
                        }

                    }

                    //TIME_FACTOR
                    double score = Double.MinValue;
                    foreach (AbstractStrategy strategy in choosenStrategies)
                    {
                        if (strategy.getStrategyType() == StrategyType.OffnsiveHelp)
                        {
                            if (strategy.getInvolvedRobots().Count == 1)
                            {
                                RobotController partner = strategy.getInvolvedRobots()[0];
                                double tmp = SimpleFunctions.judgePosition(partner);
                                if (tmp > score)
                                {
                                    score = tmp;
                                    //trzeba to moze bedzie troszke stiuningowac :) - zeby podawal na dobieg - a moze nie warto w kontkscie stregi dla 2 ??
                                    passPoint = new Point2D(strategy.getInvolvedRobots()[0].robotState.x, strategy.getInvolvedRobots()[0].robotState.y);
                                }
                            }
                        }
                    }
                    if (passPoint == null)
                    {
                        break;
                    }
                    double positionFactor = score * CLEAR_WAY_FACTOR / SimpleFunctions.MAGIC_NUMBER;
      
                    if (positionFactor < 0)
                    {
                        break;
                    }
                    //TIME FACTOR
                    tmpShotSpot = calculateShotPoint(robot);
                    double timeFactor = -1 * (TIME_FACTOR + CLEAR_WAY_FACTOR);
                    if (tmpShotSpot != null)
                    {
                        if (SimpleFunctions.isAnybodyOnTheWay(robot, new Geometry.Point2D(tmpShotSpot.x, tmpShotSpot.y)))
                        {
                            continue;
                        }
                        else
                        {
                            timeFactor = ((TOO_LONG - eta) / TOO_LONG) * TIME_FACTOR;
                        }
                    }
                    if ((timeFactor + positionFactor) > maxScore)
                    {
                        maxScore = timeFactor + positionFactor;
                        shotSpot = tmpShotSpot;
                        involvedRobots.Clear();
                        involvedRobots.Add(robot);
                    }
                    
                }
            }
            return (int)maxScore;
        }
        private Point2D calculateShotPoint(RobotController robot)
        {
            eta = 0.0;
            
            Point2D ballPosition;
            Point2D shotPoint=null;
            while (shotPoint==null) {
                eta += 0.05;
                if (eta > TOO_LONG)
                {
                    break;
                }
                ballPosition = Predicator.GetBallPosition(eta);
                toGoal = new Vector2D(ballPosition, passPoint);
                toGoal.Normalize();
                BezierCurve bc = BezierCurveDriver.calculateBezzierCurve(robot.robotState, ballPosition, PotencialDriver.maxVelocity, toGoal);
                double distance;
                if (bc == null)
                {
                    continue;
                }
                else
                {
                    distance = bc.calculateLength(CALCULATE_STEPS);
                    double calculatedEta = distance / PotencialDriver.maxVelocity;
                    if (calculatedEta < eta)
                    {
                        shotPoint = ballPosition;
                    }
                }

           }
           return shotPoint;
        }
        public SimplePassStrategy(ref AGHDriver driver)
        {
            this.driver = driver;
            involvedRobots = new List<RobotController>(1);
            type = StrategyType.Passing;
        }


            
        
        override public void execute()
        {
                   if (!finished)
                   {
                       if (shotSpot!=null) 
                       {
                           BezierCurve bc = BezierCurveDriver.calculateBezzierCurve(involvedRobots[0].robotState, shotSpot, PotencialDriver.maxVelocity, toGoal);

                           double distance;
                           if (bc != null)
                           {
                               distance = bc.calculateLength(CALCULATE_STEPS);
                               double calculatedVelocity = distance / eta;

                               BezierCurveDriver.driveWithVelocityVector(involvedRobots[0].robotState, shotSpot.x, shotSpot.y, calculatedVelocity, toGoal);
                               Point2D robotPosition = new Point2D(involvedRobots[0].robotState.x, involvedRobots[0].robotState.y);
                               if (robotPosition.GetDistance(shotSpot) < 0.01)
                               {
                                   finished = true;
                               }
                           }
                       }
                       return;
      
                   }
        }   
    }
}
